<script setup lang="ts">
  import routeComponentName from '@/config/route-component-name'
  import Pagination from '@/components/Pagination/index.vue'
  import { useRoute, useRouter } from 'vue-router'
  import { computed, onMounted, ref } from 'vue'
  import { useGetOrderList, useSetOrderListFromBrowserLocal } from '../hooks/useOrder'
  import { useFindTemplateById } from '../hooks/useTemplateList'
  import {
    ChildFormConfig,
    ComponentListItem,
    ComponentType,
    CustomChildFormFieldVal,
    CustomFormFieldVal,
    DataManagerFilterCondition,
  } from '../hooks/types'
  import { TableColumnCtx } from 'element-plus'
  import { cloneDeep } from 'lodash-es'
  import DetailDrawer from './detail-drawer/index.vue'
  import { useTagsViewStore } from '@/store/modules/tagsView'

  interface SpanMethodProps {
    row: { id: string; value: TableListItem }
    column: TableColumnCtx<Record<string, string>>
    rowIndex: number
    columnIndex: number
  }

  type TableListItem = Record<
    string,
    {
      value: string
      componentType: ComponentType
      labelName: string
      isChildForm: boolean
      mergeConfig: {
        row: number
        column: number
      }
      isStart: boolean
    }
  >

  interface SearchFilterConditionOption {
    label: string
    value: string
    isChildFormField: boolean
    childFormId: string
  }

  const { orderList, orderListTotal, getOrderListLoading, getOrderList } = useGetOrderList()
  const { template, findLoading, findTemplate } = useFindTemplateById()

  defineOptions({
    name: routeComponentName.order.customTemplateDataManager,
  })

  const route = useRoute()
  const getFieldValueStrategy = {
    input: (fieldValue: CustomFormFieldVal) => fieldValue.inputVal,
    textarea: (fieldValue: CustomFormFieldVal) => fieldValue.textareaVal,
    radio: (fieldValue: CustomFormFieldVal) => fieldValue.radioVal,
    'single-select': (fieldValue: CustomFormFieldVal) => fieldValue.singleSelectVal,
    address: (fieldValue: CustomFormFieldVal) => {
      const { province, city, area, town, address } = fieldValue.addressVal
      return `${province}-${city}-${area}-${town}-${address}`
    },
    checkbox: (fieldValue: CustomFormFieldVal) => fieldValue.checkboxVal.join('、'),
    'date-time': (fieldValue: CustomFormFieldVal) => fieldValue.datetimeVal,
    'multiple-select': (fieldValue: CustomFormFieldVal) => fieldValue.multipleSelectVal.join('、'),
    'file-upload': (fieldValue: CustomFormFieldVal) => fieldValue.fileUploadVal,
  }
  const tableData = ref<Array<{ id: string; value: TableListItem }>>([])
  const detailDrawerVisible = ref(false)
  const templateId = ref('')
  const visitingOrderId = ref('')
  const router = useRouter()
  const tagsViewStore = useTagsViewStore()
  const searchFilterPopoverVisible = ref(false)
  const searchFilter = ref<Array<DataManagerFilterCondition>>([
    {
      condition: '',
      value: '',
      fieldId: '',
      isChildFormField: false,
      childFormId: '',
      valueOptions: [],
      values: [],
    },
  ])
  const searchFilterConditionOptions = computed(() => {
    const result: Array<SearchFilterConditionOption> = []

    template.value.componentList
      .filter((component) => !['child-form', 'data-connect'].includes(component.type))
      .forEach((component) => {
        result.push({
          label: component.label,
          value: component.id,
          isChildFormField: false,
          childFormId: '',
        })
      })

    template.value.componentList
      .filter((component) => component.type === 'child-form')
      .forEach((component) => {
        component.childFormConfig.forEach((childFormField) => {
          result.push({
            label: childFormField.label,
            value: childFormField.id,
            isChildFormField: true,
            childFormId: component.id,
          })
        })
      })

    return result
  })
  const dataFilterStrategy = {
    equal: (filter: DataManagerFilterCondition) => {
      let result: { id: string; value: TableListItem } = { id: '', value: {} }

      tableData.value.forEach((order) => {
        if (order.value[filter.fieldId].value === filter.value) {
          result = order
        }
      })

      return [result]
    },
    unEqual: (filter: DataManagerFilterCondition) => {
      const result: Array<{ id: string; value: TableListItem }> = []

      tableData.value.forEach((order) => {
        if (order.value[filter.fieldId].value === filter.value) {
          result.push(order)
        }
      })

      return result
    },
    equalAny: (filter: DataManagerFilterCondition) => {
      const result: Array<{ id: string; value: TableListItem }> = []
      tableData.value.forEach((order) => {
        filter.values.forEach((value) => {
          if (order.value[filter.fieldId].value === value) {
            result.push(order)
          }
        })
      })
      return result
    },
    unEqualAny: (filter: DataManagerFilterCondition) => {
      const result: Array<{ id: string; value: TableListItem }> = []
      tableData.value.forEach((order) => {
        filter.values.forEach((value) => {
          if (order.value[filter.fieldId].value === value) {
            result.push(order)
          }
        })
      })
      return result
    },
    include: (filter: DataManagerFilterCondition) => {
      const result: Array<{ id: string; value: TableListItem }> = []
      tableData.value.forEach((order) => {
        if (order.value[filter.fieldId].value.includes(filter.value)) {
          result.push(order)
        }
      })
      return result
    },
    exclude: (filter: DataManagerFilterCondition) => {
      const result: Array<{ id: string; value: TableListItem }> = []
      tableData.value.forEach((order) => {
        if (!order.value[filter.fieldId].value.includes(filter.value)) {
          result.push(order)
        }
      })
      return result
    },
  }

  const dataFilterStrategyFnCall = (
    type: DataManagerFilterCondition['condition'],
    filter: DataManagerFilterCondition,
  ) => {
    return dataFilterStrategy[type](filter)
  }

  const getComponentValue = (
    componentType: ComponentType,
    componentValue: CustomFormFieldVal | CustomChildFormFieldVal,
  ) => {
    if (!getFieldValueStrategy[componentType]) {
      return ''
    }
    return getFieldValueStrategy[componentType](componentValue)
  }

  const createComponentConfig = (
    component: ComponentListItem,
    componentValue: CustomFormFieldVal,
  ) => {
    return {
      value: getComponentValue(component.type, componentValue),
      componentType: component.type,
      labelName: component.label,
      isChildForm: component.type === 'child-form',
      mergeConfig: {
        row: 1,
        column: 1,
      },
      isStart: true,
    }
  }

  const createChildFormFieldConfig = (
    field: ChildFormConfig,
    fieldVal: CustomChildFormFieldVal,
  ) => {
    return {
      value: getComponentValue(field.fieldType, fieldVal),
      componentType: field.fieldType,
      labelName: field.label,
      isChildForm: true,
      mergeConfig: {
        column: 1,
        row: 1,
      },
      isStart: false,
    }
  }

  /**
   * 创建表格行基础对象
   * @param order - 原工单对象
   */
  const createBaseRow = (order: {
    id: string
    value: Record<
      string,
      {
        value: CustomFormFieldVal | null
        label: string
        type: ComponentType | null
      }
    >
  }) => {
    const result: { id: string; value: TableListItem } = {
      id: order.id,
      value: {},
    }

    for (const [componentId, componentValue] of Object.entries(order.value)) {
      const component = template.value.componentList.find(
        (componentRow) => componentRow.id === componentId,
      )
      if (component) {
        result.value[componentId] = createComponentConfig(component, componentValue.value)
      }
    }

    return result
  }

  /**
   * 处理工单单中的子表单组件数据
   * @param order - 订单对象，包含子表单组件值
   * @returns 包含两个属性的对象:
   *          childFormValueArr - 所有子表单组件的值数组
   *          maxLengthChildFormValue - 拥有最多行数的子表单组件
   */
  const processChildFormComponents = (order: {
    id: string
    value: Record<
      string,
      {
        value: CustomFormFieldVal | null
        label: string
        type: ComponentType | null
      }
    >
  }) => {
    const childFormValueArr: Array<{
      value: Array<Record<string, CustomChildFormFieldVal>>
      componentId: string
    }> = []

    let maxLengthChildFormValue: {
      componentId: string
      value: Array<Record<string, CustomChildFormFieldVal>>
    } = {
      componentId: '',
      value: [],
    }

    for (const [componentId, componentValue] of Object.entries(order.value)) {
      if (!!componentValue.value && componentValue.type === 'child-form') {
        childFormValueArr.push({
          componentId,
          value: componentValue.value.childFormVal,
        })

        if (componentValue.value.childFormVal.length > maxLengthChildFormValue.value.length) {
          maxLengthChildFormValue = {
            componentId,
            value: componentValue.value.childFormVal,
          }
        }
      }
    }

    return {
      childFormValueArr,
      maxLengthChildFormValue,
    }
  }

  /**
   * 根据组件id寻找组件对象
   * @param id - 组件id
   */
  const findComponentById = (id: string) => {
    return template.value.componentList.find((item) => item.id === id)
  }

  const pushNoChildFormValueTableItem = () => {
    orderList.value.forEach((order) => {
      const isTableHasValue = Object.values(order.value)
        .filter((item) => item.type === 'child-form')
        .some((item) => item.value)

      if (!isTableHasValue) {
        tableData.value.push(createBaseRow(order))
      }
    })
  }

  /**
   * 实现逻辑
   * 1、将所有的表格的数据都放到一个数组里
   * 2、拿到选择值最多的表格
   * 3、遍历值最多的表格
   * 4、拿值最多的表格的每一行索引，到每个表格里拿数据，如果拿不到就置空
   */
  const pushHasChildFormValueTableItem = () => {
    orderList.value.forEach((order) => {
      const isTableHasValue = Object.values(order.value)
        .filter((item) => item.type === 'child-form')
        .some((item) => item.value)
      if (!isTableHasValue) return

      const addRow = createBaseRow(order)
      const { childFormValueArr, maxLengthChildFormValue } = processChildFormComponents(order)
      maxLengthChildFormValue.value.forEach((tableRow, tableRowIndex) => {
        const childFormAddRow = cloneDeep(addRow)
        childFormValueArr.forEach((item) => {
          const component = findComponentById(item.componentId)
          if (component && item.value[tableRowIndex]) {
            for (const [fieldId, fieldVal] of Object.entries(item.value[tableRowIndex])) {
              const field = component.childFormConfig.find((config) => config.id === fieldId)

              if (field) {
                childFormAddRow.value[fieldId] = createChildFormFieldConfig(field, fieldVal)
                childFormAddRow.value[fieldId].mergeConfig.row = item.value.length
              }
            }
          }
          for (let key in childFormAddRow.value) {
            childFormAddRow.value[key].mergeConfig.row = maxLengthChildFormValue.value.length
          }
        })
        for (let key in childFormAddRow.value) {
          childFormAddRow.value[key].isStart = tableRowIndex === 0
        }
        tableData.value.push(childFormAddRow)
      })

      if (!maxLengthChildFormValue.componentId) {
        tableData.value.push(addRow)
      }
    })
  }

  /**
   * 表格单元格合并回调
   * @param row
   * @param column
   * @param columnIndex
   */
  const tableSpanMethodFnCall = ({ row, column, columnIndex }: SpanMethodProps) => {
    let result = {
      rowspan: 1,
      colspan: 1,
    }

    if (columnIndex === 0) {
      if (Object.values(row.value)[0].isStart) {
        result = {
          rowspan: Object.values(row.value)[0].mergeConfig.row,
          colspan: Object.values(row.value)[0].mergeConfig.column,
        }
      } else {
        result = {
          rowspan: 0,
          colspan: 0,
        }
      }
    }

    if (row.value[column.property] && !row.value[column.property].isChildForm) {
      if (row.value[column.property].isStart) {
        result = {
          rowspan: row.value[column.property].mergeConfig.row,
          colspan: row.value[column.property].mergeConfig.column,
        }
      } else {
        result = {
          rowspan: 0,
          colspan: 0,
        }
      }
    }

    return result
  }

  /**
   * 表格初始化
   */
  const tableInit = () => {
    tableData.value.length = 0
    pushNoChildFormValueTableItem()
    pushHasChildFormValueTableItem()
  }

  /**
   * 数据初始化
   */
  const dataInit = async () => {
    useSetOrderListFromBrowserLocal()
    if (route.params.id) {
      templateId.value = route.params.id as string
      await getOrderList(route.params.id as string)
      await findTemplate(route.params.id as string)
    }
  }

  /**
   * 表格行点击事件
   * @param row - 表格行对象
   */
  const handleTableRowClick = (row: { id: string; value: TableListItem }) => {
    visitingOrderId.value = row.id
    detailDrawerVisible.value = true
  }

  /**
   * 创建工单点击事件
   */
  const onCreateOrderClick = () => {
    router.push({ path: `/order/custom/initiate/process/${templateId.value}` })
  }

  /**
   * 工单详情弹窗更新回调
   */
  const onDetailDrawerUpdate = () => {
    init()
  }

  /**
   * 关闭页面
   */
  const closePage = () => {
    tagsViewStore.delView(route.path)
    router.push({ path: '/order/custom/templates' })
  }

  /**
   * 筛选条件下拉框的选项显示事件
   * @param visible - 显示状态
   * @param filter - 筛选条件
   * @param filterIndex - 筛选条件索引
   */
  const handleSearchFilterValueVisibleChange = (
    visible: boolean,
    filter: DataManagerFilterCondition,
    filterIndex: number,
  ) => {
    if (!visible) return
    if (!filter.isChildFormField) {
      searchFilter.value[filterIndex].valueOptions.length = 0
      orderList.value.forEach((order) => {
        searchFilter.value[filterIndex].valueOptions.push(
          getComponentValue(order.value[filter.fieldId].type, order.value[filter.fieldId].value),
        )
      })
      return
    }
  }

  /**
   * 筛选字段下拉选项点击事件
   * @param searchFilterIndex - 筛选条件索引
   * @param filter - 筛选对象
   */
  const handleSearchFilterConditionOptionClick = (
    searchFilterIndex: number,
    filter: SearchFilterConditionOption,
  ) => {
    searchFilter.value[searchFilterIndex].fieldId = filter.value
    searchFilter.value[searchFilterIndex].isChildFormField = filter.isChildFormField
    searchFilter.value[searchFilterIndex].childFormId = filter.childFormId
  }

  /**
   * 页面初始化
   */
  const init = async () => {
    await dataInit()
    tableInit()
  }

  /**
   * 筛选弹出框的筛选按钮点击事件
   */
  const onFilterClick = () => {
    const tempTableData: Array<{ id: string; value: TableListItem }> = []
    searchFilter.value.forEach((filter) => {
      if (!filter.isChildFormField) {
        tempTableData.push(...dataFilterStrategyFnCall(filter.condition, filter))
      }
    })

    tableData.value.length = 0
    tempTableData.forEach((data) => {
      if (!tableData.value.map((order) => order.id).includes(data.id)) {
        tableData.value.push(data)
      }
    })

    searchFilterPopoverVisible.value = false
  }

  /**
   * 筛选弹出框清空点击事件
   */
  const onFilterClearClick = () => {
    searchFilter.value = [
      {
        condition: '',
        value: '',
        fieldId: '',
        isChildFormField: false,
        childFormId: '',
        valueOptions: [],
        values: [],
      },
    ]

    init()
    searchFilterPopoverVisible.value = false
  }

  onMounted(() => {
    init()
  })
</script>

<template>
  <div v-loading="getOrderListLoading || findLoading" class="custom-template-data-manager">
    <div class="container">
      <div class="header">
        <div class="btn-group">
          <h-button @click="closePage">返回</h-button>
          <h-plain-button @click="onCreateOrderClick">新建工单</h-plain-button>
        </div>
        <div class="search">
          <el-popover
            :visible="searchFilterPopoverVisible"
            trigger="click"
            placement="bottom-end"
            width="500"
          >
            <template #reference>
              <h-button
                type="primary"
                @click="searchFilterPopoverVisible = !searchFilterPopoverVisible"
              >
                <el-icon>
                  <Filter />
                </el-icon>
                筛选
              </h-button>
            </template>

            <div class="filter-card">
              <div class="add-filter-btn">
                <i class="iconfont icon-tianjia"></i>
                添加筛选条件
              </div>

              <div class="filter-list">
                <div
                  v-for="(filter, filterIndex) in searchFilter"
                  :key="filterIndex"
                  class="filter-item"
                >
                  <div class="field">
                    <el-select v-model="filter.fieldId">
                      <el-option
                        v-for="(condition, conditionIndex) in searchFilterConditionOptions"
                        :key="conditionIndex"
                        :label="condition.label"
                        :value="condition.value"
                        @click="handleSearchFilterConditionOptionClick(filterIndex, condition)"
                      />
                    </el-select>
                  </div>
                  <div class="condition">
                    <el-select v-model="filter.condition" :disabled="!filter.fieldId">
                      <el-option value="equal" label="等于" />
                      <el-option value="unEqual" label="不等于" />
                      <el-option value="equalAny" label="等于任意一个" />
                      <el-option value="unEqualAny" label="不等于任意一个" />
                      <el-option value="include" label="包含" />
                      <el-option value="exclude" label="不包含" />
                    </el-select>
                  </div>
                  <div class="value">
                    <el-select
                      v-if="['equal', 'unEqual'].includes(filter.condition)"
                      v-model="filter.value"
                      :disabled="!filter.fieldId || !filter.condition"
                      @visible-change="(visible: boolean) => handleSearchFilterValueVisibleChange(visible, filter, filterIndex)"
                    >
                      <el-option
                        v-for="(valueOption, valueOptionIndex) in filter.valueOptions"
                        :key="valueOptionIndex"
                        :label="valueOption"
                        :value="valueOption"
                      />
                    </el-select>
                    <el-select
                      v-if="['equalAny', 'unEqualAny'].includes(filter.condition)"
                      v-model="filter.values"
                      class="search-filter-value-multiple"
                      :disabled="!filter.fieldId || !filter.condition"
                      :multiple="true"
                      @visible-change="(visible: boolean) => handleSearchFilterValueVisibleChange(visible, filter, filterIndex)"
                    >
                      <el-option
                        v-for="(valueOption, valueOptionIndex) in filter.valueOptions"
                        :key="valueOptionIndex"
                        :label="valueOption"
                        :value="valueOption"
                      />
                    </el-select>
                    <el-input
                      v-if="['include', 'exclude'].includes(filter.condition)"
                      v-model.trim="filter.value"
                    />
                  </div>
                  <div class="del-btn">
                    <i class="iconfont icon-shanchu2"></i>
                  </div>
                </div>
              </div>

              <div class="filter-card-footer">
                <h-button type="primary" @click="onFilterClick">筛选</h-button>
                <h-button @click="onFilterClearClick">清空</h-button>
              </div>
            </div>
          </el-popover>
        </div>
      </div>
      <div class="table-pagination">
        <div class="table">
          <el-table
            :border="true"
            height="100%"
            :data="tableData"
            :span-method="tableSpanMethodFnCall"
            scrollbar-always-on
            @row-click="handleTableRowClick"
          >
            <el-table-column
              v-for="(component, componentIndex) in template.componentList.filter(
                (item) => item.type !== 'data-connect',
              )"
              :key="componentIndex"
              show-overflow-tooltip
              :label="component.label"
              min-width="140"
              :prop="component.id"
            >
              <template #default="{ row }">
                <template v-if="component.type === 'child-form'">
                  <el-table-column
                    v-for="(
                      childFormField, childFormFieldIndex
                    ) in component.childFormConfig.filter(
                      (item) => item.fieldType !== 'data-connect',
                    )"
                    :key="childFormFieldIndex"
                    show-overflow-tooltip
                    :label="childFormField.label"
                    min-width="140"
                  >
                    <template #default="{ row: childFormRow }">
                      {{
                        childFormRow.value[childFormField.id]
                          ? childFormRow.value[childFormField.id].value
                          : ''
                      }}
                    </template>
                  </el-table-column>
                </template>

                <template v-else>
                  {{ row.value[component.id].value }}
                </template>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <div class="pagination">
          <pagination :list_total="orderListTotal" />
        </div>
      </div>
    </div>

    <detail-drawer
      v-model:visible="detailDrawerVisible"
      :template-id="templateId"
      :order-id="visitingOrderId"
      @update="onDetailDrawerUpdate"
    />
  </div>
</template>

<style scoped lang="scss">
  .search-filter-value-multiple {
    :deep(.el-select__wrapper) {
      height: fit-content !important;
    }
  }

  .filter-card {
    display: flex;
    flex-direction: column;
    row-gap: 12px;

    .add-filter-btn {
      cursor: pointer;
    }

    .filter-list {
      display: flex;
      flex-direction: column;

      .filter-item {
        display: flex;
        column-gap: 8px;
        align-items: center;

        .condition {
          width: 140px;
        }

        .field,
        .value {
          flex: 1;
        }
      }
    }

    .filter-card-footer {
      display: flex;
      column-gap: 8px;
    }
  }

  .custom-template-data-manager {
    width: 100%;
    height: calc(100vh - 92px);
    padding: 12px;
    box-sizing: border-box;

    .container {
      background-color: #fff;
      box-sizing: border-box;
      width: 100%;
      height: 100%;
      padding: 12px;
      display: flex;
      flex-direction: column;
      row-gap: 12px;

      .header {
        display: flex;
        justify-content: space-between;

        .btn-group {
          display: flex;
          column-gap: 8px;
        }

        .search {
          display: flex;
          column-gap: 8px;

          .search-icon {
            cursor: pointer;

            &:hover {
              color: #007cff;
            }
          }
        }
      }

      .table-pagination {
        flex: 1;
        display: flex;
        flex-direction: column;
        row-gap: 12px;

        .table {
          max-height: 100%;
        }

        .pagination {
          display: flex;
          justify-content: flex-end;
        }
      }
    }
  }
</style>
